//
//  SyncViewController.m
//  auditorias
//
//  Created by Mauro on 7/30/13.
//  Copyright (c) 2013 Antilope. All rights reserved.
//

#import "SyncViewController.h"
#import "MBProgressHUD.h"
#import "DataLoader.h"
#import "SharedMemory.h"
#import "UIPlaceHolderTextView.h"
#import "AuditType.h"
#import "PointOfSell.h"
#import "ControlVariables.h"
#import "Audit.h"
#import "User.h"
#import "JSON.h"
#import <math.h>

@interface SyncViewController ()

@end

@implementation SyncViewController

@synthesize buttonSync;
@synthesize progressBar;
@synthesize progressBarLayout;
@synthesize textViewProgressMessage;
@synthesize textViewProgressCount;
@synthesize pathNamesPDVsOriginal;
@synthesize pathNamesAuditsOriginal;
@synthesize pathNamesPDVs;
@synthesize pathNamesAudits;
@synthesize failedCommits;


- (void) dealloc
{
    [buttonSync release], buttonSync = nil ;
    [progressBar release], progressBar = nil;
    [progressBarLayout release], progressBarLayout = nil;
    [textViewProgressMessage release], textViewProgressMessage = nil;
    [textViewProgressCount release], textViewProgressCount = nil;
    [pathNamesPDVsOriginal release], pathNamesPDVsOriginal = nil;
    [pathNamesAuditsOriginal release], pathNamesAuditsOriginal = nil;
    [pathNamesPDVs release], pathNamesPDVs = nil;
    [pathNamesAudits release], pathNamesAudits = nil;
    [_topBarView release];
    [super dealloc];
}

- (void)viewDidUnload
{
    self.buttonSync = nil;
    self.progressBar = nil;
    self.progressBarLayout = nil;
    self.textViewProgressMessage = nil;
    self.textViewProgressCount = nil;
    self.pathNamesPDVsOriginal = nil;
    self.pathNamesAuditsOriginal = nil;
    self.pathNamesPDVs = nil;
    self.pathNamesAudits = nil;
    [super viewDidUnload];
}

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view.
    [TopBarViewController setTitleLabelOf:_topBarView text:kTopBarTitleSync];
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    //do stuff
}

- (void)viewWillDisappear:(BOOL)animated
{
    //do stuff
    [super viewWillDisappear:animated];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (IBAction)syncButtonTapped:(id)sender
{  
    self.failedCommits = -1;
    self.textViewProgressCount.hidden = true;
    
    self.pathNamesPDVs = [[[NSMutableArray alloc] init] autorelease];
    self.pathNamesAudits = [[[NSMutableArray alloc] init] autorelease];
    self.failedCommits = 0;
    [SharedMemory fillPathNamesArraysWithPathNamesPDVs:self.pathNamesPDVs pathNamesAudits:self.pathNamesAudits  ];
    self.pathNamesPDVsOriginal = [[[NSMutableArray alloc] initWithArray:self.pathNamesPDVs] autorelease];
    self.pathNamesAuditsOriginal = [[[NSMutableArray alloc] initWithArray:self.pathNamesAudits] autorelease];
    [self showSpinner];
    [self sendFiles];
    //dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, (unsigned long)NULL), ^(void) {
    
    //});
    
}

- (void) sendFiles
{
    SharedMemory* mem = [SharedMemory sharedInstance];
    //First send the PDVs and/or add the PDVs to the list
    while([self.pathNamesPDVs count]!=0){
        
        NSString* pathPDV = [self.pathNamesPDVs objectAtIndex:0];
        NSString* internalIdPDV = [PointOfSell getIdFromPath:pathPDV ];
        PointOfSell* pdv = [SharedMemory findPDVByInternalId:internalIdPDV];
        //When there is no PDV found, make one and add it to the list
        if (pdv==nil){
            pdv = [self makePDVFromPath:pathPDV];
            [mem.pointsOfSell addObject:pdv];
        }
        //When it has no external id, it should be sent
        if ([pdv.externalId isEqualToString:@""] ) {
            mem.commitPointOfSellInternalId = internalIdPDV;
            DataLoader *loader = [[DataLoader alloc] initWithCaller:self successSel:@selector(dataReadyWithLoader:) failureSel:@selector(dataNotReadyWithLoader:)];
            //If succeed it will put the Id on the pdv
            //Log.d("sync", "PDV va a enviarse con id_interno:"+pdv.getInternalId());
            [loader postPointOfSell: [pdv toJSON]];
            return;
        }
        //If the pdv has an external id, remove it from the list and restart
        else{
            //Log.d("sync", "PDV va a removerse con id_interno:"+pdv.getInternalId() + "e id_externo:"+pdv.getId());
            [self.pathNamesPDVs removeObjectAtIndex:0];
        }
    }
    
    //Time to send the  Audits
    while([self.pathNamesPDVs count]==0 && [self.pathNamesAudits count]!=0){
        self.textViewProgressCount.hidden = false;
        [self.textViewProgressMessage setText:syncronizing_audits];
        [self updateSpinner];
        NSString* pathAudit = [self.pathNamesAudits objectAtIndex:0];
        NSString* internalIdPDV = [Audit getPDVInternalIdFromPath:pathAudit];
        //When its an Audit made from a custom PDV
        if (![internalIdPDV isEqualToString:@""]) {
            PointOfSell* pdv = [SharedMemory findPDVByInternalId:internalIdPDV ];
            //When the PDV corresponding does not exist or has no external id, then its an error
            if (pdv==nil || [pdv.externalId isEqualToString:@""]) {
                self.failedCommits++;
                [self.pathNamesAudits removeObjectAtIndex:0];
            }
            //Else the Audit needs the PDV ID and the tail of the JSON before submitting
            else{
                DataLoader *loader = [[DataLoader alloc] initWithCaller:self successSel:@selector(dataReadyWithLoader:) failureSel:@selector(dataNotReadyWithLoader:)];
                [loader postAudit: [NSString stringWithFormat:@"%@%@", [self makeAuditStringFromPath:pathAudit], [Audit getPDVAndEnding:pdv.externalId ] ]];
                return;
            }
        }
        //When the Audir uses a PDV from the list
        else{
            DataLoader *loader = [[DataLoader alloc] initWithCaller:self successSel:@selector(dataReadyWithLoader:) failureSel:@selector(dataNotReadyWithLoader:)];
            [loader postAudit: [NSString stringWithFormat:@"%@", [self makeAuditStringFromPath:pathAudit] ]];
            return;
        }
    }
    
    //If both lists are empty, finish the Sync
    if([self.pathNamesPDVs count]==0 && [self.pathNamesAudits count]==0){
        [self endSync];
    }
}


- (NSString*) makeAuditStringFromPath:(NSString*) pathAudit
{
    @try {
        NSString *filePath = [[SharedMemory getDocumentsDir] stringByAppendingPathComponent:pathAudit];
        NSString* jsonString = [[[NSString alloc] initWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil] autorelease];
        //SBJSON *parser = [[SBJSON alloc] init];
        //NSArray* jsonArray = [parser objectWithString:jsonString error:nil];
        //[parser release];
        
        //JSONParser jParser = new JSONParser();
        //InputStream inputstream = openFileInput(pathAudit);
        //return jParser.getStringFromTextFile(inputstream);
        return jsonString;
    }
    @catch (NSException * e) { NSLog(@"%@",e.description); }
    return @"";
}


- (PointOfSell*) makePDVFromPath:(NSString*) pathPDV
{
    @try {
        NSString *filePath = [[SharedMemory getDocumentsDir] stringByAppendingPathComponent:pathPDV];
        NSString* jsonString = [[[NSString alloc] initWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil] autorelease];
        SBJSON *parser = [[SBJSON alloc] init];
        NSArray* jsonArray = [parser objectWithString:jsonString error:nil];
        [parser release];
        PointOfSell* pdv = [[[PointOfSell alloc] initWithDictionary:[jsonArray objectAtIndex:0] ] autorelease];
        return pdv;
    }
    @catch (NSException * e) { NSLog(@"%@",e.description); }
    return nil;
}

- (void) endSync
{
    if (self.failedCommits==0){
        //Delete all the PDV files
        [SharedMemory deleteAllFilesForPDVs:true forAudits:false];
        //To mark ALL the AuditTypes + PDV as done (can't use the other approach because the PDV and Audit Type can't be easily obtained from the audit file).
        [SharedMemory forgetAllKeysOn:UNSYNC_AUDITS_KEY];
        //Update the last sync date
        [SharedMemory rememberTodayOn:SHARED_PREFS_LAST_SYNC];
        //End with a message
        [self hideSpinner];
        [SharedMemory showError:server_sync_finish_ok_title andText:server_sync_finish_ok];
    }
    else{
        [self hideSpinner];
        [SharedMemory showError:server_sync_finish_fail_title andText:server_sync_finish_fail];
    }
    
}

- (void) showMessage: (NSString*) message
{
    dispatch_async(dispatch_get_main_queue(), ^{
        //tasks on main thread
        NSLog(@"INFO: %@",message);
    });
}

- (void)dataReadyWithLoader:(DataLoader*) dataLoader;
{
    int loaderType = dataLoader.callType;
    @try {
        [dataLoader release];
    }
    @catch (NSException * e) { }
    
    SharedMemory* mem = [SharedMemory sharedInstance];
    
    if (loaderType==TYPE_ADD_POINTOFSALE){
        NSString* pathNamePDV = [self.pathNamesPDVs objectAtIndex:0];
        NSString* internalIdPDV = mem.commitPointOfSellInternalId;
        PointOfSell* pdv = [SharedMemory findPDVByInternalId:internalIdPDV];
        //Rewrite file now with the external id
        [SharedMemory createTextFile:pathNamePDV data:[pdv toInternalJSON]];
        
        //Show sign
        [self showMessage:message_pdv_sending_success];
        //Removes the path from the list and continues
        [self.pathNamesPDVs removeObjectAtIndex:0];
        [self sendFiles];
        return;
    }
    
    else if (loaderType==TYPE_ADD_AUDIT){
        
        NSString* auditFileName =[self.pathNamesAudits objectAtIndex:0];
        //Deletes the file
        [SharedMemory deletePathName:auditFileName];
        [self showMessage:message_audit_sending_success];
        //Removes the path from the list and continues
        [self.pathNamesAudits removeObjectAtIndex:0];
        [self sendFiles];
        return;
    }
}

- (void)dataNotReadyWithLoader:(DataLoader*) dataLoader;
{
    int loaderType = dataLoader.callType;
    @try {
        [dataLoader release];
    }
    @catch (NSException * e) { }
    
    self.failedCommits++;
    
    if (loaderType==TYPE_ADD_POINTOFSALE){
        [self showMessage:message_pdv_sending_fail];
        [self.pathNamesPDVs removeObjectAtIndex:0];
        [self sendFiles];
        return;
    }
    
    else if (loaderType==TYPE_ADD_AUDIT){
        [self showMessage:message_audit_sending_fail];
        [self.pathNamesAudits removeObjectAtIndex:0];
        [self sendFiles];
        return;
    }
}


-(void) updateSpinner
{
    dispatch_async(dispatch_get_main_queue(), ^{
        //tasks on main thread
        int remaining = [self.pathNamesAudits count];
        int total = [self.pathNamesAuditsOriginal count];;
        NSString* counter = @"";
        if (self.textViewProgressCount.hidden==false)
            counter = [NSString stringWithFormat:@"%d/%d",(total-remaining),total ];
        [textViewProgressCount setText:counter];
        if([self.pathNamesAuditsOriginal count] !=0){
            float progress = 1.0 - remaining*1.0/total ;
            [self.progressBar setProgress:progress];
        }
        else
            [self.progressBar setProgress:0.0];
    });    
}



-(void) showSpinner
{
    dispatch_async(dispatch_get_main_queue(), ^{
        //tasks on main thread
        //To set the full screen
        [self.progressBarLayout removeFromSuperview]; //Removes the lock
        [self.tabBarController.view addSubview:self.progressBarLayout]; //Sets the lock
        self.buttonSync.hidden = true;
        self.progressBarLayout.hidden = false;
    });
    [self updateSpinner];
}

/**
 * Hides the spinner
 */
-(void) hideSpinner
{
    dispatch_async(dispatch_get_main_queue(), ^{
        //tasks on main thread
        self.buttonSync.hidden = false;
        self.progressBarLayout.hidden = true;
    });
}

@end
